Inbuilt Data Structures

Data Structures in a language determine the level of flexibility of using the language. If a Language has efficient, inbuilt data structures then the effort of the programmer is reduced. He does not have to code everything from the scratch. Furthermore, if it has user friendly syntax, it also makes the code more readable.

Python accounts for both readability and efficiency. It provides many inbuilt data structure classes that are suitable for day to day programming. In next 4 chapters, we will look at the details of lists,tuples,sets and dictionarys.

First, let's look at Zen of Python - Python Design Principles


In [1]:
import this


The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Python is designed according to this philosophy. Now we shall examine basic data structures which comes handy in our journey of Python.

Lists

List is a mutable collection of elements(may be of same or different types), which is indexed by a 0-based integer. Lists are so much like C arrays. But the capability of Python lists called Slicing makes them more powerful.

Creating Lists

  • Creating an empty list

    x = []  # [] denotes a list type
          # or
          x = list()
    
  • Creating list with some initial elements

    x = [2,3,0,'g']
    

In [1]:
x = [1,2,4,5]

In [2]:
x


Out[2]:
[1, 2, 4, 5]

Accessing List elements

List elements can be accessed by 0-based integer index as in C. In addition to this, Negative indexes are also supported. If x is a list, x[-1] gives 1st element from the last, x[-2] gives second element from the last and so on...


In [3]:
x[3]


Out[3]:
5

In [4]:
x[-2]


Out[4]:
4

Obtaining Partitions of the List - Slicing

One can extract a portion of a list, and modify the value of it. If x is a list, it is achieved by a statement in the form of

x[start:stop:step]

It returns elements of x from index start to the index stop (excluding stop) in the steps of step. These 3 arguments are not mandatory. If not specified start is set to 0, stop is set to length of list and step is set to 1


In [5]:
x = [1,2,5,6,7,0,3]

In [6]:
x[1:3]  # Access from x[1] to x[2]


Out[6]:
[2, 5]

In [7]:
x[2:5:2] # Access from x[2] to x[4] in the steps of 2


Out[7]:
[5, 7]

In [8]:
x[1:3] = [6] # They can modify original list

In [9]:
x   # Look at modified list, 6 is replaced twice


Out[9]:
[1, 6, 6, 7, 0, 3]

In [25]:
x[::-1] # Access the array in reverse order


Out[25]:
[3, 0, 7, 6, 6, 1]

In [10]:
x[:]  # Returns copy of list x


Out[10]:
[1, 6, 6, 7, 0, 3]

You have observed that slices return a list, which have the reference to original list. Hence modifying slice results the change in original array.

Deleting List elements by index - del

If the position of element to be deleted is known, it can be deleted by del statement

To delete the ith element of list x,

del x[i]

In [11]:
del x[2]

In [12]:
x


Out[12]:
[1, 6, 7, 0, 3]

Using Operators on List


In [13]:
x = [4,3,5,0,1]
y = [2,1,5,4,0]

In [14]:
x + y


Out[14]:
[4, 3, 5, 0, 1, 2, 1, 5, 4, 0]
**Note** `x + y` returns a new list that contains elements of `y` appended to `x`. This has no effect on original lists `x` and `y`

In [15]:
y * 2


Out[15]:
[2, 1, 5, 4, 0, 2, 1, 5, 4, 0]

Operations on List

Unlike the Operators, operations performed on list can act directly on lists and may not return anything

Here are some of operations on list. They are member functions of class list. If x is a list,

  • x.append(elem) - adds a single element to the end of the list. It does not return the new list, just modifies the original list x.
  • x.insert(index, elem) - inserts the element at the given index, shifting elements to the right.
  • x.extend(list2) - adds the elements in list2 to the end of the list. Using + or += on a list is similar to using extend().
  • x.index(ele) - searches for the given element from the start of the list and returns its index. Throws a ValueError if the element does not appear (use in to check without a ValueError).
  • x.remove(elem) - searches for the first instance of the given element and removes it (throws ValueError if not present)
  • x.sort() - sorts the list in place (does not return it). (The sorted() function is preferred.)
  • x.reverse() - reverses the list in place (does not return it)
  • x.pop(index) - removes and returns the element at the given index. Returns the rightmost element if index is omitted (roughly the opposite of append()).

In [16]:
x = [0,3,7,2,1]

In [17]:
x.append(9)
x


Out[17]:
[0, 3, 7, 2, 1, 9]

In [18]:
x.insert(4,4)
x


Out[18]:
[0, 3, 7, 2, 4, 1, 9]

In [19]:
x.extend([8,7,6])
x


Out[19]:
[0, 3, 7, 2, 4, 1, 9, 8, 7, 6]

In [20]:
x.remove(6)
x


Out[20]:
[0, 3, 7, 2, 4, 1, 9, 8, 7]

In [21]:
x.sort()
x


Out[21]:
[0, 1, 2, 3, 4, 7, 7, 8, 9]

In [22]:
x.reverse()
x


Out[22]:
[9, 8, 7, 7, 4, 3, 2, 1, 0]

In [23]:
x.pop()


Out[23]:
0

In [24]:
x.pop(0)


Out[24]:
9

In [25]:
x


Out[25]:
[8, 7, 7, 4, 3, 2, 1]

In [26]:
sorted(x)


Out[26]:
[1, 2, 3, 4, 7, 7, 8]

List elements can also be lists, which gives 2-D array like structure


In [27]:
x = [[2,3,4],
     [1,2,2],
     [2,3,4]]

In [28]:
x[1]


Out[28]:
[1, 2, 2]

In [29]:
x[2][1]


Out[29]:
3
**Note** There is no rule that the length of each sublist in a list must be same

Obtaining length of list - len


In [30]:
x = [1,2,3]
len(x)


Out[30]:
3

In [31]:
x = [[2,3,4],2,['a','v']]

In [32]:
len(x)


Out[32]:
3

Membership Operator in

in operator can be used to check the existance of an element in the list


In [33]:
x = [1,2,3,0,5,4]
4 in x


Out[33]:
True

In [34]:
10 in x


Out[34]:
False

Converting an iterator to list

Using yield keyword, one can create an iterator. Using list(), one can make a list of all values yielded by iterator


In [60]:
list(range(10))


Out[60]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]